(function(angular) {
	'use strict';

	angular.module('fs.modal', [ 'ui.bootstrap', 'modalTemplate' ])
	.directive('fsDraggable', draggableDirevtive)
	.directive('fsResizeable', resizeableDirevtive)
	.controller('messageDialogsController', messageDialogsController)
	.provider('modalService', modalServiceProvider);
	
	angular.module("modalTemplate", []).run($templateCache);

	draggableDirevtive.$inject = [ '$document', '$timeout' ];
	function draggableDirevtive($document, $timeout) {
		return {
			restrict : 'A',
			link : function($scope, element, $attr) {
				var startX = 0, startY = 0, x = 0, y = 0, initialized = false, dialog;
				initDrag(1);
				function initDrag(count){
					var dialogEl, titleEl, title;
					dialogEl = $document[0].querySelector("div[index='" + $attr.index + "'].modal");
					if (!dialogEl) {
						return;
					}
					titleEl = dialogEl.querySelector(".modal-header");
					if (!dialogEl || !titleEl) {
						if (count <= 20) {
							$timeout(function() {
								initDrag(++count);
							}, 100);
						}
						return;
					}
					dialog = angular.element(dialogEl);
					title = angular.element(titleEl);
					title.css({
						position : 'relative',
						cursor : 'move'
					});

					title.on('mousedown', function(event) {
						// Prevent default dragging of selected content
						event.preventDefault();
						if (!initialized) {
							x = dialogEl.offsetLeft;
							y = dialogEl.offsetTop;
							initialized = true;
						}
						startX = event.clientX - x;
						startY = event.clientY - y;
						$document.on('mousemove', mouseMove);
						$document.on('mouseup', mouseUp);
					});
				}

				function mouseMove(event) {
					var bodyElement = $document[0].querySelector('body');
					var maxY = bodyElement.offsetHeight - startY - 20;
					var maxX = bodyElement.offsetWidth - startX - 20;
					y = event.clientY - startY;
					x = event.clientX - startX;
					if (x < 0) {
						x = 0;
					}
					if (x > maxX) {
						x = maxX;
					}

					if (y < -20) {
						y = -20;
					}
					if (y > maxY) {
						y = maxY;
					}
					$timeout(function() {
						dialog.css({
							left : x + 'px',
							top : y + 'px'
						});
					});
				}

				function mouseUp() {
					$document.off('mousemove', mouseMove);
					$document.off('mouseup', mouseUp);
				}
			}
		};
	}
	
	resizeableDirevtive.$inject = [ '$document', '$timeout' ];
	function resizeableDirevtive($document, $timeout) {
		return {
			restrict : 'A',
			link : function($scope, $element, $attr) {
				var startX = 0, startY = 0, dialogWidth, contentBodyWidth, contentBodyHeight, dialogEl, dialog, contentBodyEl, contentBody, right, bright, bleft, disableReszie = 0;
				initResize();
				function initResize() {
					var rightEL, brightEl, bleftEl, dialogWindowEl, contentEl, content;
					dialogWindowEl = $document[0].querySelector("div[index='" + $attr.index + "'].modal");
					if (!dialogWindowEl) {
						return;
					}
					dialogEl = dialogWindowEl.querySelector(".modal-dialog");
					if (!dialogEl) {
						return;
					}
					contentEl = dialogWindowEl.querySelector(".app-modal-content");
					if (!contentEl) {
						return;
					}
					contentBodyEl = contentEl.querySelector(".modal-body");
					if (!contentBodyEl) {
						return;
					}
					
					dialog = angular.element(dialogEl);
					content = angular.element(contentEl);
					contentBody = angular.element(contentBodyEl);
					
					content.append("<div class=\"resize-right\"></div>");
					content.append("<div class=\"resize-bottom-right\"></div>");
					content.append("<div class=\"resize-bottom-left\"></div></div>");
					
					rightEL = contentEl.querySelector(".resize-right");
					brightEl = contentEl.querySelector(".resize-bottom-right");
					bleftEl = contentEl.querySelector(".resize-bottom-left");
					
					right = angular.element(rightEL);
					bright = angular.element(brightEl);
					bleft = angular.element(bleftEl);
					
					right.on('mousedown', function(event) {
						// Prevent default dragging of selected content
						event.preventDefault();
						dialogWidth = dialogEl.offsetWidth;
						contentBodyWidth = contentBodyEl.offsetWidth;
						contentBodyHeight = contentBodyEl.offsetHeight;
						startX = event.clientX;
						startY = event.clientY;
						disableReszie = 1;
						$document.on('mousemove', mouseHorizontalMove);
						$document.on('mouseup', mouseUp);
					});
					
					bleft.on('mousedown', function(event) {
						// Prevent default dragging of selected content
						event.preventDefault();
						dialogWidth = dialogEl.offsetWidth;
						contentBodyWidth = contentBodyEl.offsetWidth;
						contentBodyHeight = contentBodyEl.offsetHeight;
						startX = event.clientX;
						startY = event.clientY;
						disableReszie = 2;
						$document.on('mousemove', mouseVerticalMove);
						$document.on('mouseup', mouseUp);
					});
					
					bright.on('mousedown', function(event) {
						// Prevent default dragging of selected content
						event.preventDefault();
						dialogWidth = dialogEl.offsetWidth;
						contentBodyWidth = contentBodyEl.offsetWidth;
						contentBodyHeight = contentBodyEl.offsetHeight;
						startX = event.clientX;
						startY = event.clientY;
						disableReszie = 0;
						$document.on('mousemove', mouseMove);
						$document.on('mouseup', mouseUp);
						
					});
				}
				
				function mouseHorizontalMove(event) {
					mouseMove(event);
				}

				function mouseVerticalMove(event) {
					mouseMove(event);
				}

				function mouseMove(event) {
					dialogWidth = disableReszie != 2 ? (dialogWidth + event.clientX - startX) : dialogWidth;
					contentBodyWidth = disableReszie != 2 ? (contentBodyWidth + event.clientX - startX) : contentBodyWidth;
					contentBodyHeight = disableReszie != 1 ? (contentBodyHeight + event.clientY - startY) : contentBodyHeight;
					startX = event.clientX;
					startY = event.clientY;
					$timeout(function() {
						dialog.css({
							width : dialogWidth + 'px',
						});
						contentBody.css({
							width : contentBodyWidth + 'px',
							height : contentBodyHeight + 'px'
						});
					});
				}

				function mouseUp() {
					$document.off('mousemove', mouseMove);
					$document.off('mousemove', mouseVerticalMove);
					$document.off('mousemove', mouseHorizontalMove);
					$document.off('mouseup', mouseUp);
				}
			}
		};
	}

	messageDialogsController.$inject = [ '$rootScope', '$scope', '$timeout', '$uibModalInstance', '$translate', 'dialogsOptions', 'modalService' ];
	function messageDialogsController($rootScope, $scope, $timeout, $uibModalInstance, $translate, dialogsOptions, modalService) {
		var ctrl = this, dialogMessages, resultMessages = [];
		ctrl.title = dialogsOptions.title;
		$rootScope.$uibModalInstance = $uibModalInstance;
		//support the i18n message which has the param {0}, {1}and etc. 
		dialogMessages = angular.copy(dialogsOptions.messages);
		angular.forEach(dialogMessages, function(message, index) {
			var paramObj = {}, args = message.args, msg = message.msg;
			if(msg != undefined && args != undefined) {
				if(!angular.isArray(args)) {
					var newArray = [];
					newArray.push(args);
					args = newArray;
				}
				$translate(args).then(
						function (objs) {
							angular.forEach(args, function(key, index) {
								paramObj['p'+index] = objs[args[index]];
							});
							$translate(msg, paramObj).then(
								function (msg) {
									resultMessages.push(msg);
									ctrl.messages = resultMessages;
								}, function (msg) {
									resultMessages.push(msg);
									ctrl.messages = resultMessages;
								}
							);
						}
					, function () {
						$translate(msg, paramObj).then(
							function (msg) {
								resultMessages.push(msg);
								ctrl.messages = resultMessages;
							}, function (msg) {
								resultMessages.push(msg);
								ctrl.messages = resultMessages;
							}
						);
					});
			} else {
				ctrl.messages = dialogMessages;
			}
		});
		
		ctrl.redirections = dialogsOptions.redirections;
		ctrl.dialogsOptions = dialogsOptions;
		ctrl.close = function() {
			if (!dialogsOptions.btnCallback || !dialogsOptions.btnCallback['close'] || dialogsOptions.btnCallback['close']() !== false) {
				$uibModalInstance.dismiss();
			}
		};
		ctrl.ok = function() {
			if (!dialogsOptions.btnCallback || !dialogsOptions.btnCallback['ok'] || dialogsOptions.btnCallback['ok'](true) !== false) {
				$uibModalInstance.close();
			}
		};
		ctrl.promptOk = function() {
			if (!ctrl.promptMessage) {
				modalService.openErrorDialogs({
					messages : [ 'title.dialogs.comments.required' ]
				});
				return;
			}
			if (!dialogsOptions.btnCallback || !dialogsOptions.btnCallback['ok'] || dialogsOptions.btnCallback['ok'](ctrl.promptMessage) !== false) {
				$uibModalInstance.close();
			}
		};
		ctrl.promptOkAndCloseButtons = [
	          {
	              "name": "close",
	              "label": "nux.button.text.close",
	              "type": "button",
	              "btnClass": "btn-default",
	              "options": {
	                  "icon": "close",
	                  "callback": {
	                      "click": "vm.close"
	                  }
	              },
	              "btnScope": $scope
	          },
	          {
	              "name": "promptOk",
	              "label": "nux.button.text.ok",
	              "type": "button",
	              "btnClass": "btn-primary",
	              "options": {
	                  "icon": "ok",
	                  "callback": {
	                      "click": "vm.promptOk"
	                  }
	              },
	              "btnScope": $scope
	          }
	          
	    ];
		ctrl.okAndCloseButtons = [
	          {
	              "name": "close",
	              "label": "nux.button.text.cancel",
	              "type": "button",
	              "btnClass": "btn-default",
	              "options": {
	                  "icon": "close",
	                  "callback": {
	                      "click": "vm.close"
	                  }
	              },
	              "btnScope": $scope
	          },
	          {
	              "name": "ok",
	              "label": "nux.button.text.confirm",
	              "type": "button",
	              "btnClass": "btn-primary",
	              "options": {
	                  "icon": "ok",
	                  "callback": {
	                      "click": "vm.ok"
	                  }
	              },
	              "btnScope": $scope
	          }
	    ];
		ctrl.closeButtons = [
	          {
	              "name": "close",
	              "label": "nux.button.text.close",
	              "type": "button",
	              "btnClass": "btn-primary",
	              "options": {
	                  "icon": "close",
	                  "callback": {
	                      "click": "vm.close"
	                  }
	              },
	              "btnScope": $scope
	          }
	    ];
		ctrl.redirect = function(redirection) {
			if (redirection.state) {
				$scope.go(redirection.state, redirection.params);
			}
			$uibModalInstance.dismiss();
		};
		ctrl.jump = function(redirection) {
			if (redirection.jump && angular.isFunction(redirection.jump)) {
				redirection.jump();
			}else if(redirection.state){
				$scope.go(redirection.state, redirection.params);
			}
			$uibModalInstance.dismiss();
		};
		if (dialogsOptions.autoClose === true) {
			$uibModalInstance.rendered.then(function(){
				$timeout(function() {
					if (!dialogsOptions.cancelAutoClose) {
						ctrl.close();
					}
				}, dialogsOptions.autoCloseInterval * 1000);
			}, angular.noop);
		}
	}

	modalServiceProvider.$inject = [];
	function modalServiceProvider() {
		var provider = this;
		provider.dialogsModules = {};
		provider.loadingCount = 0;
		provider.loadingInstance = null;
		provider.loadingOptions = {
			//windowTemplateUrl : 'uib/template/modal/window.html',
			template : '<div class="icon-loading"></div>\n',
			size : 'sm',
			backdrop : 'static',
			keyboard : false,
			animation : false
		};
		provider.setDialogsModule = function(name, options) {
			provider.dialogsModules[name] = options;
		};
		provider.modalOptions = {
			size : 'lg',
			level : 'info',
			blocked : false,
			backdrop : 'static',
			keyboard : true,
			animation : true
		// windowTemplateUrl : 'pti/template/modal/window.html',
		// appendTo : provider.appendTo,
		// scope : provider.scope
		// backdropClass: '',
		// controller: '',
		// controllerAs: '',
		// openedClass:'',
		// resolve:{},
		// template: '',
		// templateUrl: '',
		// windowClass: '',
		// resolve : object or function
		};
		provider.$get = modalService;
		modalService.$inject = [ '$rootScope', '$uibModal', '$uibPosition', '$window', '$document', '$q', '$log', '$timeout', 'routerService' ];
		function modalService($rootScope, $uibModal, $uibPosition, $window, $document, $q, $log, $timeout, routerService) {
			provider.modalOptions.scope = $rootScope;
			provider.modalOptions.appendTo = angular.element($document[0].querySelector('.modal-container'));
			function moveToCenter() {
				var modalElements = $document[0].querySelectorAll('.dialogModal'),modal, top, left;
				angular.forEach(modalElements, function(modalElement) {
					var  modalContent, css = {};
					move(1);
					function move(count) {
						modalContent = modalElement.querySelector('.modal-content');
						top = ($window.innerHeight - modalElement.offsetHeight) * 2 / 5 / $window.innerHeight * 100;
						left = ($window.innerWidth - modalElement.offsetWidth) / 2 / $window.innerWidth * 100;
						if (top == 0 || !modalContent) {
							if (count <= 20) {
								$timeout(function() {
									move(++count);
								}, 10);
							}
							return;
						}
						if (top <= 0) {
							css.top = '30px';
						} else {
							css.top = top + '%';
						}
						if (left > 0) {
							css.left = left + '%';
						}
						modal = angular.element(modalElement);
						modal.css(css);
					}
				});
			}
			
			function openLoading() {
			    if (!provider.loadingInstance) {
			     provider.loadingOptions.appendTo = angular.element($document[0].querySelector('.modal-container'));
			     provider.loadingInstance = openModalDialogs(provider.loadingOptions);
			     ++provider.loadingCount;
			    } else {
			     ++provider.loadingCount;
			    }
			}
			
			function closeLoading() {
			    var i = 50;
			    if (provider.loadingInstance) {
			     --provider.loadingCount;
			     if (provider.loadingCount <= 0 && !provider.loadingInstance._closing) {
			      while (provider.loadingInstance && i <= 1000) {
			       i += 50;
			       provider.loadingInstance._closing = true;
			       $timeout(_closeLoading, i);
			      }
			     }
			    }
			 }
			
			function _closeLoading() {
			    if (provider.loadingCount <= 0 && provider.loadingInstance) {
			     provider.loadingInstance.close();
			     provider.loadingInstance = null;
			     provider.loadingCount = 0;
			    } else if (provider.loadingInstance) {
			     $timeout(_closeLoading, 50);
			    }
			}
			
			function openModalDialogs(modalOptions) {
				var dialogsInstance;
				modalOptions.backdrop = !modalOptions.backdrop ? 'static' : modalOptions.backdrop;
				dialogsInstance = $uibModal.open(modalOptions);
				dialogsInstance.closed.then(function(arg) {
					var modalOpener = $document[0].activeElement;
					if (modalOpener && modalOpener.blur) {
						modalOpener.blur();
					}
				});
				dialogsInstance.rendered.then(moveToCenter, angular.noop);
				return dialogsInstance;
			}
			function openDialogs(modalOptions) {
				var dialogsInstance;
				if (modalOptions.blocked == true) {
					modalOptions.backdrop = !modalOptions.backdrop ? 'static' : modalOptions.backdrop;
				} else {
					modalOptions.backdrop = false;
				}
				dialogsInstance = $uibModal.open(modalOptions);
				dialogsInstance.closed.then(function(arg) {
					var modalOpener = $document[0].activeElement;
					if (modalOpener && modalOpener.blur) {
						modalOpener.blur();
					}
				});
				dialogsInstance.rendered.then(moveToCenter, angular.noop);
				return dialogsInstance;
			}
			function openWarningDialogs(options) {
				var dialogsInstance, modalOptions, defaultOption;
				options.title = options.title || 'title.dialogs.warning';
				options.level = options.level || 'warning';
				options.icon = options.icon || 'warning';
				options.messages = options.messages || [];
				defaultOption = {
					templateUrl : options.templateUrl || 'pti/template/modal/messages.html',
					controller : 'messageDialogsController',
					controllerAs : 'vm',
					windowTopClass : options.windowTopClass,
					animation : options.animation === undefined ? true : options.animation,
					resolve : {
						dialogsOptions : function() {
							return options;
						}
					}
				};
				modalOptions = angular.extend({}, provider.modalOptions, defaultOption);
				modalOptions.size = options.size || [400, 100];
				modalOptions.blocked = options.blocked;
				if (modalOptions.size && angular.isArray(modalOptions.size)) {
					options.bodyStyle = {
							width : modalOptions.size[0] + 'px',
							height : modalOptions.size[1] + 'px'
					};
				}
				dialogsInstance = openDialogs(modalOptions);
				return dialogsInstance;
			}
			function openAcknowledgeDialogs(options) {
				var dialogsInstance, modalOptions, defaultOption = {
					templateUrl : options.templateUrl || 'pti/template/modal/acknowledge.html',
					controller : 'messageDialogsController',
					controllerAs : 'vm',
					windowTopClass : options.windowTopClass,
					animation : options.animation === undefined ? true : options.animation,
					resolve : {
						dialogsOptions : function() {
							return options;
						}
					}
				};
				options.title = options.title || 'title.dialogs.acknowledge';
				options.messages = options.messages || [];
				options.level = 'info';
				options.icon = 'complete';
				options.windowTopClass = 'fade-out';
				options.animation = false;
				modalOptions = angular.extend({}, provider.modalOptions, defaultOption);
				modalOptions.size = options.size || [400, 100];
				modalOptions.level = options.level;
				if (modalOptions.size && angular.isArray(modalOptions.size)) {
					options.bodyStyle = {
							width : modalOptions.size[0] + 'px',
							height : modalOptions.size[1] + 'px'
					};
				}
				dialogsInstance = openModalDialogs(modalOptions);
				return dialogsInstance;
			}
			function openJumpDialogs(options) {
				var dialogsInstance, modalOptions, defaultOption = {
					templateUrl : options.templateUrl || 'pti/template/modal/jump.html',
					controller : 'messageDialogsController',
					controllerAs : 'vm',
					windowTopClass : options.windowTopClass,
					animation : options.animation === undefined ? true : options.animation,
					resolve : {
						dialogsOptions : function() {
							return options;
						}
					}
				};
				options.title = options.title || 'title.dialogs.acknowledge';
				options.messages = options.messages || [];
				options.level = 'info';
				options.icon = 'complete';
				options.windowTopClass = 'fade-out';
				options.animation = false;
				modalOptions = angular.extend({}, provider.modalOptions, defaultOption);
				modalOptions.size = options.size || [400, 100];
				modalOptions.level = options.level;
				if (modalOptions.size && angular.isArray(modalOptions.size)) {
					options.bodyStyle = {
							width : modalOptions.size[0] + 'px',
							height : modalOptions.size[1] + 'px'
					};
				}
				dialogsInstance = openModalDialogs(modalOptions);
				return dialogsInstance;
			}
			function openErrorDialogs(options) {
				var dialogsInstance;
				options.title = options.title || 'title.dialogs.error';
				options.autoClose = (options.autoClose == true);
				options.autoCloseInterval = options.autoCloseInterval || 3;
				options.level = 'error';
				options.icon = 'failed';
				dialogsInstance = openWarningDialogs(options);
				return dialogsInstance;
			}
			function openInfoDialogs(options) {
				var dialogsInstance;
				options.title = options.title || 'title.dialogs.info';
				options.autoClose = (options.autoClose == true);
				options.autoCloseInterval = options.autoCloseInterval || 3;
				options.level = 'info';
				options.icon = 'regular';
				dialogsInstance = openWarningDialogs(options);
				return dialogsInstance;
			}
			function openSuccessDialogs(options) {
				var dialogsInstance;
				options.title = options.title || 'title.dialogs.success';
				options.autoClose = (options.autoClose == true);
				options.autoCloseInterval = options.autoCloseInterval || 3;
				options.level = 'success';
				options.icon = 'success';
				dialogsInstance = openWarningDialogs(options);
				return dialogsInstance;
			}
			// for log dialog
			function openLogDialogs(options) {
				var dialogsInstance, modalOptions, defaultOption = {
					templateUrl : options.templateUrl || 'pti/template/modal/logMessages.html',
					controller : 'messageDialogsController',
					controllerAs : 'vm',
					windowTopClass : options.windowTopClass,
					animation : options.animation === undefined ? true : options.animation,
					resolve : {
						dialogsOptions : function() {
							return options;
						}
					}
				};
				options.title = options.title || 'title.dialogs.info';
				options.messages = options.messages || [];
				modalOptions = angular.extend({}, provider.modalOptions, defaultOption);
				modalOptions.level = 'info';
				dialogsInstance = openDialogs(modalOptions);
				return dialogsInstance;
			}
			function openConfirmDialogs(options) {
				var dialogsInstance, modalOptions, defaultOption = {
					templateUrl : options.templateUrl || 'pti/template/modal/confirmMessages.html',
					controller : 'messageDialogsController',
					controllerAs : 'vm',
					windowTopClass : options.windowTopClass,
					animation : options.animation === undefined ? true : options.animation,
					resolve : {
						dialogsOptions : function() {
							return options;
						}
					}
				};
				options.title = options.title || 'title.dialogs.confirm';
				options.level = options.level || 'info';
				if (options.level == 'info') {
					options.icon = options.icon || 'regular';
				} else if (options.level == 'warning') {
					options.icon = options.icon || 'warning';
				} else if (options.level == 'success') {
					options.icon = options.icon || 'success';
				} else if (options.level == 'error') {
					options.icon = options.icon || 'failed';
				} else {
					options.icon = 'failed';
				}
				options.messages = options.messages || [];
				modalOptions = angular.extend({}, provider.modalOptions, defaultOption);
				modalOptions.size = options.size || [400, 100];
				modalOptions.blocked = true;
				if (modalOptions.size && angular.isArray(modalOptions.size)) {
					options.bodyStyle = {
							width : modalOptions.size[0] + 'px',
							height : modalOptions.size[1] + 'px'
					};
				}
				dialogsInstance = openModalDialogs(modalOptions);
				return dialogsInstance;
			}
			function openPromptDialogs(options) {
				var dialogsInstance, modalOptions, defaultOption = {
					templateUrl : options.templateUrl || 'pti/template/modal/promptInput.html',
					controller : 'messageDialogsController',
					controllerAs : 'vm',
					windowTopClass : options.windowTopClass,
					animation : options.animation === undefined ? true : options.animation,
					resolve : {
						dialogsOptions : function() {
							return options;
						}
					}
				};
				options.title = options.title || 'title.dialogs.prompt';
				options.messages = options.messages || [];
				options.level = options.level || 'info';
				options.icon = options.icon || 'regular';
				modalOptions = angular.extend({}, provider.modalOptions, defaultOption);
				modalOptions.size = [ 400, 100 ];
				modalOptions.blocked = true;
				if (modalOptions.size && angular.isArray(modalOptions.size)) {
					options.bodyStyle = {
						width : modalOptions.size[0] + 'px',
						height : modalOptions.size[1] + 'px'
					};
				}
				dialogsInstance = openModalDialogs(modalOptions);
				return dialogsInstance;
			}
			function openCustomDialogs(options) {
				var dialogsInstance, modalOptions, dialogsModule, defaultOption, dependentFiles, layoutConfig, i18nConfig, validatorConfig, authorizationConfig;
				var cacheLayout = false,
				cacheResource = false,
				cacheAuthorization = false,
				cacheValidationRule = false;
				dialogsModule = angular.merge({}, provider.dialogsModules[options.dialogsModule]);
				dialogsModule.disableButton = function($event) {
					var btn = ($event.srcElement || $event.target).parentElement;
					if (btn.disabled) {
						return false;
					}
					btn.disabled = true;
					$timeout(function() {
						btn.disabled = false;
					}, 500);
				};
				if (dialogsModule.templateUrl) {
					dialogsModule.templateUrl = dialogsModule.templateUrl.replace('${theme}', routerService.getTheme());
				}
				dependentFiles = dialogsModule.dependentFiles;
				layoutConfig = dialogsModule.layoutConfig;
				i18nConfig = dialogsModule.i18nConfig;
				validatorConfig = dialogsModule.validatorConfig;
				authorizationConfig = dialogsModule.authorizationConfig;
				function getFormValidateMessages(formCtrls) {
					var errors = {};
					angular.forEach(formCtrls, function(formCtrl) {
						if (formCtrl.validateErrors) {
							angular.merge(errors, formCtrl.validateErrors);
						}
						if (formCtrl._formCtrls) {
							angular.merge(errors, getFormValidateMessages(formCtrl._formCtrls));
						}
					});
					return angular.equals({}, errors) ? null : errors;
				}
				//show error Messages if the form is invalid.
				dialogsModule.showErrorMessages = function(topFormCtrl) {
					var errors = getFormValidateMessages([topFormCtrl]);
					if (errors) {
						openErrorDialogs({
							'title' : '',
							'messages' : errors
						});
					}
				};
				dependentFileFn.$inject = [ '$ocLazyLoad' ];
				function dependentFileFn($ocLazyLoad) {
					angular.forEach(dependentFiles, function(filePath, index){
						dependentFiles[index] = filePath.replace('${theme}', routerService.getTheme());
					});
					return $ocLazyLoad.load(dependentFiles, {
						cache : true
					});
				}
				layoutConfigFn.$inject = [ '$rootScope', '$q', 'Constants', 'ajaxServiceFactory', 'storageService' ];
				function layoutConfigFn($rootScope, $q, Constants, ajaxServiceFactory, storageService) {
					var url = layoutConfig, ajaxService, siteInfo, defer = $q.defer();
					if (!url) {
						return $q.resolve({});
					}
					siteInfo = storageService.getSiteInfo();
					if (options.params && options.params.siteCode && siteInfo && siteInfo.siteCode
							&& options.params.siteCode != siteInfo.siteCode) {
						url = url + "/" + options.params.siteCode;
					}
					ajaxService = ajaxServiceFactory.buildAjaxService({
						loadConfig : {
							'url' : url,
							'method' : 'post',
							'cache' : cacheLayout
						}
					});
					var params = {};
					if (options.params && options.params.parmCat) params.parmCat = options.params.parmCat;
					if (options.params && options.params.parmSubcat) params.parmSubcat = options.params.parmSubcat;
					ajaxService.loadConfig(params).then(function(response) {
						defer.resolve(response ? response.data : {});
					}, function(error) {
						log.debug('can not load config[' + url + ']:' + error);
						defer.reject();
					});
					return defer.promise;
				}

				i18nConfigFn.$inject = [ '$rootScope', '$q', 'Constants', 'storageService', 'ajaxServiceFactory' ];
				function i18nConfigFn($rootScope, $q, Constants, storageService, ajaxServiceFactory) {
					var ajaxService, defer = $q.defer();
					if (!i18nConfig) {
						return $q.resolve({});
					}
					ajaxService = ajaxServiceFactory.buildAjaxService({
						loadConfig : {
							'url' : i18nConfig,
							'method' : 'get',
							'cache' : cacheResource
						}
					});
					ajaxService.loadConfig().then(function(response) {
						defer.resolve(loadResource($rootScope, Constants.NOTIFY_CHANGE_LANGUAGE, Constants.SESSION_I18N_RESOURES, storageService, response ? response.data : null));
					}, function error(error) {
						log.debug('can not load config[' + url + ']:' + error);
						defer.reject();
					});

					return defer.promise;
				}

				authorizationConfigFn.$inject = [ '$rootScope', '$q', '$stateParams', 'Constants', 'ajaxServiceFactory' ];
				function authorizationConfigFn($rootScope, $q, $stateParams, Constants, ajaxServiceFactory) {
					var ajaxService, defer = $q.defer();
					if (!authorizationConfig) {
						return $q.resolve({});
					}
					ajaxService = ajaxServiceFactory.buildAjaxService({
						loadConfig : {
							'url' : authorizationConfig,
							'method' : 'get',
							'cache' : cacheAuthorization
						}
					});
					ajaxService.loadConfig().then(function(response) {
						$stateParams.authorization = buildAuthService($rootScope, Constants, ajaxServiceFactory, response ? response.data : {});
						defer.resolve($stateParams.authorization);
					}, function error(error) {
						log.debug('can not load config[' + url + ']:' + error);
						defer.reject();
					});
					return defer.promise;
				}

				validatorConfigFn.$inject = [ '$rootScope', '$q', 'Constants', 'storageService', 'ajaxServiceFactory' ];
				function validatorConfigFn($rootScope, $q, Constants, storageService, ajaxServiceFactory) {
					var ajaxService, defer = $q.defer();
					if (!validatorConfig) {
						return $q.resolve({});
					}
					ajaxService = ajaxServiceFactory.buildAjaxService({
						loadConfig : {
							'url' : validatorConfig,
							'method' : 'get',
							'cache' : cacheValidationRule
						}
					});
					ajaxService.loadConfig().then(function(response) {
						var resources = (response && response.data) ? response.data.resources : null;
						if (resources) {
							loadResource($rootScope, Constants.NOTIFY_CHANGE_LANGUAGE, Constants.SESSION_I18N_VALIDATION_RESOURES, storageService, resources);
							$rootScope.$emit(Constants.NOTIFY_CHANGE_LANGUAGE, {
								'language' : language
							});
						}
						defer.resolve((response && response.data) ? (response.data.rules || {}) : {});
					}, function error(error) {
						log.debug('can not load config[' + url + ']:' + error);
						defer.reject();
					});

					return defer.promise;
				}

				function buildAuthService($rootScope, Constants, ajaxServiceFactory, authorizationConfig) {
					var authorizationServices = {}, authService, emptyServiceNames = [];
					angular.forEach(authorizationConfig, function(value, key) {
						if (value == '') {
							emptyServiceNames.push(key);
						} else {
							authorizationServices[key] = {
								url : value,
								method : 'post',
								cache : true
							};
						}
					});
					authService = ajaxServiceFactory.buildAjaxService(authorizationServices) || {};
					angular.forEach(emptyServiceNames, function(value, key) {
						authService[value] = angular.noop;
					});
					return authService;
				}

				function loadResource($rootScope, notifyType, resourceType, storageService, resources) {
					if (resources) {
						storageService.setItemToSession(resourceType, resources);
						$rootScope.$emit(notifyType);
					}
					return resources;
				}
				
				options.title = options.title || (dialogsModule.title || 'title.dialogs.lookup');
				options.params = options.params || {};
				options.btnCallback = options.btnCallback || {};
				if (!options.size) {
					delete options.size;
				}
				angular.merge(dialogsModule, options);
				dialogsModule.size = dialogsModule.size || [800,500];
				dialogsModule.level = options.level || 'info';
				dialogsModule.icon = options.icon || 'regular';
				if (dialogsModule.size && angular.isArray(dialogsModule.size)) {
					dialogsModule.bodyStyle = {
						width : dialogsModule.size[0] + 'px',
						height : dialogsModule.size[1] + 'px'
					};
				}
				defaultOption = {
					templateUrl : options.custormerTemplateUrl || 'pti/template/modal/custormer.html',
					size : dialogsModule.size,
					controller : dialogsModule.controller,
					controllerAs : dialogsModule.controllerAs,
					windowTopClass : options.windowTopClass,
					animation : options.animation === undefined ? true : options.animation,
					resolve : {
						dialogsModule : function() {
							return dialogsModule;
						},
						dependentFiles : dependentFileFn,
						layoutConfig : layoutConfigFn,
						i18nConfig : i18nConfigFn,
						authService : authorizationConfigFn,
						validatorConfig : validatorConfigFn
					}
				};
				modalOptions = angular.extend({}, provider.modalOptions, defaultOption);
				modalOptions.blocked = true;
				dialogsInstance = openModalDialogs(modalOptions);
				return dialogsInstance;
			}
			return {
				openLoading : openLoading,
				closeLoading : closeLoading,
				openModalDialogs : openModalDialogs,
				openDialogs : openDialogs,
				openAcknowledgeDialogs : openAcknowledgeDialogs,
				openJumpDialogs : openJumpDialogs,
				openWarningDialogs : openWarningDialogs,
				openInfoDialogs : openInfoDialogs,
				openSuccessDialogs : openSuccessDialogs,
				openErrorDialogs : openErrorDialogs,
				openConfirmDialogs : openConfirmDialogs,
				openPromptDialogs : openPromptDialogs,
				openLogDialogs : openLogDialogs,
				openCustomDialogs : openCustomDialogs
			};
		}
	}
	
	/*angular.module("uib/template/modal/window.html").run(["$templateCache", function($templateCache) {
		$templateCache.put("uib/template/modal/window.html", ''
			+ '<div class="modal-dialog {{angular.isString(size) ? \'modal-\' + size : \'\'}}"'
			+ '<div class="modal-content" uib-modal-transclude></div></div>\n' + '');
	}]);*/
	
	$templateCache.$inject = [ "$templateCache" ];
	function $templateCache($templateCache) {
		$templateCache.put('pti/template/modal/acknowledge.html', ''+
				'<div class="acknowledgeDialog app-modal-content {{vm.dialogsOptions.level}}">\n' + 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button><i ng-show="vm.dialogsOptions.icon" class="icon icon-{{vm.dialogsOptions.icon}}"></i><label class="modal-title" id="modal-title">{{vm.title|translate}}</label>\n' + 
				'    </div>\n'+ 
				'    <div class="modal-body panel jumbotron" id="modal-body" ng-style="vm.dialogsOptions.bodyStyle">\n' + 
				'             <div ng-repeat="message in vm.messages"><i class="icon icon-{{vm.dialogsOptions.icon}}"></i><span>{{message | translate }}</span></div>\n' + 
				'             <div><label>Goto:</label> <a href="#" ng-click="vm.redirect(redirection)" ng-repeat="redirection in vm.redirections"><span>{{redirection.name | translate }}</span></a></div>\n' + 
				'    </div>\n' + 
				'    <div class="modal-footer">\n'+ 
				'        <fs-button fs-button-config="button" fs-button-group="true" ng-repeat="button in vm.closeButtons"/>\n'+
				'    </div>\n' + 
				'</div>\n');
		
		$templateCache.put('pti/template/modal/jump.html', ''+
				'<div class="acknowledgeDialog app-modal-content {{vm.dialogsOptions.level}}">\n' + 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button><i ng-show="vm.dialogsOptions.icon" class="icon icon-{{vm.dialogsOptions.icon}}"></i><label class="modal-title" id="modal-title">{{vm.title|translate}}</label>\n' + 
				'    </div>\n'+ 
				'    <div class="modal-body panel jumbotron" id="modal-body" ng-style="vm.dialogsOptions.bodyStyle">\n' + 
				'             <div ng-repeat="message in vm.messages"><span>{{message | translate }}</span></div>\n' + 
				'             <div><label>Goto:</label> <a href="#" ng-click="vm.jump(redirection)" ng-repeat="redirection in vm.redirections"><span>{{redirection.name | translate }}</span></a></div>\n' + 
				'    </div>\n' + 
				'    <div class="modal-footer btn-group-sm">\n'+ 
				'        <fs-button fs-button-config="button" fs-button-group="true" ng-repeat="button in vm.closeButtons"/>\n'+
				'    </div>\n' + 
		'</div>\n');
		
		$templateCache.put('pti/template/modal/messages.html', ''+
				'<div class="messageDialog app-modal-content {{vm.dialogsOptions.level}}" ng-click="vm.dialogsOptions.cancelAutoClose = true;">\n' + 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button>\n'+
				'        <i ng-show="vm.dialogsOptions.icon" class="icon icon-{{vm.dialogsOptions.icon}}"></i>\n'+
				'        <label class="modal-title" id="modal-title">{{vm.title|translate}}</label>\n' + 
				'    </div>\n'+ 
				'    <div class="modal-body panel" id="modal-body" ng-style="vm.dialogsOptions.bodyStyle">\n' + 
				'         <ul class="list-unstyled">\n'+ 
				'             <li ng-repeat="message in vm.messages"><span>{{message | translate }}</span></li>\n' + 
				'         </ul>\n' + 
				'    </div>\n' + 
				'    <div class="modal-footer btn-group-sm" ng-if="!vm.dialogsModule.autoClose">\n'+ 
				'        <fs-button fs-button-config="button" fs-button-group="true" ng-repeat="button in vm.closeButtons"/>\n'+
				'    </div>\n' + 
				'</div>\n');

		$templateCache.put('pti/template/modal/logMessages.html',''+
				'<div class="logDialog app-modal-content {{vm.dialogsOptions.level}}">\n'+ 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button><label class="modal-title" id="modal-title">{{vm.title|translate}}</label>\n'+ 
				'    </div>\n'+ 
				'    <div class="modal-body panel" id="modal-body" ng-style="vm.dialogsOptions.bodyStyle">\n'+ 
				'       <textarea class="form-control input-sm" rows="20"><span>{{::vm.messages}}</span></textarea>\n'+ 
				'    </div>\n'+ 
				'    <div class="modal-footer btn-group-sm">\n'+ 
				'        <fs-button fs-button-config="button" fs-button-group="true" ng-repeat="button in vm.closeButtons"/>\n'+
				'    </div>\n' + 
				'</div>\n');
				
		$templateCache.put('pti/template/modal/confirmMessages.html', ''+
				'<div class="confirmDialog app-modal-content {{vm.dialogsOptions.level}}">\n' + 
				'    <div class="modal-header">\n'+ 
				'       <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button><i ng-show="vm.dialogsOptions.icon" class="icon icon-{{vm.dialogsOptions.icon}}"></i><label class="modal-title" id="modal-title">{{vm.title|translate}}</label>\n' + 
				'    </div>\n'+ 
				'    <div class="modal-body panel" id="modal-body" ng-style="vm.dialogsOptions.bodyStyle">\n' + 
				'         <ul class="list-unstyled">\n'+ 
				'             <li ng-repeat="message in vm.messages"><span>{{message | translate }}</span></li>\n'+ 
				'         </ul>\n</b>' + 
				'    </div>\n' + 
				'    <div class="modal-footer">\n'+ 
				'        <fs-button fs-button-config="button" fs-button-group="true" ng-repeat="button in vm.okAndCloseButtons"/>\n'+
				'    </div>\n' + 
				'</div>\n');
		
		$templateCache.put('pti/template/modal/promptInput.html',''+
				'<div class="promptInputDialog app-modal-content {{vm.dialogsOptions.level}}">\n'+ 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button><i ng-show="vm.dialogsOptions.icon" class="icon icon-{{vm.dialogsOptions.icon}}"></i><label class="modal-title" id="modal-title">{{vm.title|translate}}</label>\n'+ 
				'    </div>\n'+ 
				'    <div class="modal-body panel" id="modal-body" ng-style="vm.dialogsOptions.bodyStyle">\n'+ 
				'       <div class="panel-body"><textarea class="form-control input-sm" rows="3" ng-model="vm.promptMessage"></textarea></div>\n'+ 
				'    </div>\n'+ 
				'    <div class="modal-footer">\n'+ 
				'		 <fs-button fs-button-config="button" fs-button-group="true" ng-repeat="button in vm.promptOkAndCloseButtons"/>'+
				'    </div>\n' + 
				'</div>\n');
		
		$templateCache.put('pti/template/modal/custormer.html', ''+
				'<div ng-form name="{{::vm.formName}}" disableUnloadCheck="{{::vm.disableUnloadCheck}}" class="custormerDialog app-modal-content {{vm.dialogsModule.level}}">\n' + 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button><i ng-show="vm.dialogsModule.icon" class="icon icon-{{vm.dialogsModule.icon}}"></i><span class="modal-title" id="modal-title">{{vm.dialogsModule.title|translate}}</span>\n' + 
				'    </div>\n'+ 
				'    <div class="modal-body panel" id="modal-body" ng-style="vm.dialogsModule.bodyStyle">\n' + 
				'         <div ng-include="vm.dialogsModule.templateUrl"></div>\n' + 
				'    </div>\n' + 
				'    <div class="modal-footer">\n'+ 
				'        <button class="btn btn-primary" type="button" ng-if="vm.ok != undefined" ng-click="vm.dialogsModule.disableButton($event);vm.ok()"><span class="icon icon-ok pull-left"></span><span>{{"nux.button.text.ok"|translate}}</span></button>\n'+ 
				'        <button class="btn btn-default" type="button" ng-if="vm.close != undefined" ng-click="vm.close()"><span class="icon icon-close pull-left"></span><span>{{"nux.button.text.close"|translate}}</span></button>\n'+ 
				'    </div>\n' + 
				'</div>\n');
		
		$templateCache.put('pti/template/modal/custormerOfCancelAndApplyBtn.html', ''+
				'<div ng-form name="{{::vm.formName}}" disableUnloadCheck="{{::vm.disableUnloadCheck}}" class="custormerDialog app-modal-content {{vm.dialogsModule.level}}">\n' + 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.cancel()"><span aria-hidden="true" class="icon icon-closed"></span></button><i ng-show="vm.dialogsModule.icon" class="icon icon-{{vm.dialogsModule.icon}}"></i><span class="modal-title" id="modal-title">{{vm.dialogsModule.title|translate}}</span>\n' +
				'    </div>\n'+ 
				'    <div class="modal-body panel" id="modal-body" ng-style="vm.dialogsModule.bodyStyle">\n' + 
				'         <div ng-include="vm.dialogsModule.templateUrl"></div>\n' + 
				'    </div>\n' + 
				'    <div class="modal-footer">\n'+ 
				'        <button class="btn btn-default" type="button" ng-if="vm.cancel != undefined" ng-click="vm.cancel()"><span class="icon icon-noicon pull-left"></span><span>{{"nux.button.text.cancel"|translate}}</span></button>\n'+ 
				'        <button class="btn btn-primary" type="button" ng-if="vm._apply != undefined" ng-click="vm.dialogsModule.disableButton($event);vm._apply()"><span class="icon icon-noicon pull-left"></span><span>{{"nux.button.text.apply"|translate}}</span></button>\n'+ 
				'    </div>\n' + 
				'</div>\n');
		$templateCache.put('pti/template/modal/custormerOfColseAndSaveBtn.html', ''+
				'<div ng-form name="{{::vm.formName}}" disableUnloadCheck="{{::vm.disableUnloadCheck}}" class="custormerDialog app-modal-content {{vm.dialogsModule.level}}">\n' + 
				'    <div class="modal-header">\n'+ 
				'        <button type="button" class="close" data-dismiss="alert" aria-label="Close" ng-click="vm.close()"><span aria-hidden="true" class="icon icon-closed"></span></button><i ng-show="vm.dialogsModule.icon" class="icon icon-{{vm.dialogsModule.icon}}"></i><span class="modal-title" id="modal-title">{{vm.dialogsModule.title|translate}}</span>\n' +
				'    </div>\n'+ 
				'    <div class="modal-body panel" id="modal-body" ng-style="vm.dialogsModule.bodyStyle">\n' + 
				'         <div ng-include="vm.dialogsModule.templateUrl"></div>\n' + 
				'    </div>\n' + 
				'    <div class="modal-footer">\n'+ 
				'    	<div class="pull-right">\n'+ 
				'   		 <button class="btn btn-default" type="button" ng-if="vm.close != undefined" ng-click="vm.close()"><span class="icon icon-noicon pull-left"></span><span>{{"nux.button.text.close"|translate}}</span></button>\n'+ 
				'    		<button class="btn btn-primary" type="button" ng-if="vm.save != undefined" ng-click="vm.dialogsModule.disableButton($event);vm.save()"><span class="icon icon-noicon pull-left"></span><span>{{"nux.button.text.save"|translate}}</span></button>\n'+ 
				'    	</div>\n' +
				'    </div>\n' + 
				'</div>\n');
		$templateCache.put('pti/template/modal/dashboard/panel.html', ''+
				'<div class="custormerDialog">\n' + 
				'    <div class="modal-content" id="modal-body" ng-style="panelController.panelConfig.bodyStyle" ng-include="panelController.panelConfig.dashboardTemplateUrl">\n' + 
				'    </div>\n' + 
				'</div>\n');
		}
})(angular);
